/**
 * @Author: 陈瑞鹏
 * @Date:   2022-12-09 11:25:44
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2023-01-04 19:11:38
 */

import { gameConfig, soliderType } from "./gameConfig";
import { ArrowState } from "./state/ArrowState";
import { BaseState } from "./state/BaseState";
import { CirCleState } from "./state/CircleState";
import { PlayerState } from "./state/PlayerState";
import { ResState } from "./state/ResState";

// 状态定义
export interface GameSystemState {
    // 当前的时间（游戏时间）
    now: number,
    // 玩家
    players: PlayerState[],
    //右边元素
    rightBaseEles: BaseState[],
    //右边元素
    leftBaseEles: BaseState[],
    //资源
    resBaseEles: ResState[],
    //圈
    cirCleEles: CirCleState[],
    // 元素的 ID 生成
    nextBaseEle: number,
    // 飞行中的箭矢
    arrows: ArrowState[],
    // 箭矢的 ID 生成
    nextArrowId: number,
    //圈的 ID 生成
    nextCirCleId: number,
    //资源 ID 生成
    nextResId: number,
    //下次生成资源时间
    nextResTime: number,
    //游戏结束时间
    gameOverTime: number,
    //游戏状态 1 准备阶段 2 游戏进行中 3 游戏结束
    gameState: number,
    //结算数据
    resultData: any,
    //定时增加金币
    goldTime: number,
}

/**
 * 前后端复用的状态计算模块
 */
export class GameSystem {

    // 当前状态
    private _state: GameSystemState = {
        now: 0,
        players: [],
        rightBaseEles: [],
        leftBaseEles: [],
        resBaseEles: [],
        cirCleEles: [],
        arrows: [],
        nextArrowId: 1,
        nextBaseEle: 1,
        nextCirCleId: 1,
        nextResId: 1,
        nextResTime: 0,
        gameOverTime: 0, //游戏倒计时
        gameState: 1, //游戏状态 1 准备阶段 2 游戏进行中 3 游戏结束
        resultData: {},
        goldTime: 300,
    }
    get state(): Readonly<GameSystemState> {
        return this._state
    }

    // 重设状态
    reset(state: GameSystemState) {
        this._state = Object.merge({}, state);

    }

    // 应用输入，计算状态变更
    applyInput(input: GameSystemInput) {
        if (input.type === 'PlayerMove') {
            let player = this._state.players.find(v => v.id === input.playerId);
            if (!player) {
                return;
            }

        }
        else if (input.type === 'PlayerAttack') {
            let player = this._state.players.find(v => v.id === input.playerId);
            if (player) {
                let newArrow: ArrowState = {
                    id: this._state.nextArrowId++,
                    //箭矢的类型
                    arrowType: input.arrowType,
                    fromPlayerId: input.playerId,
                    targetPos: { ...input.targetPos },
                    targetTime: input.targetTime,
                    startPos: input.startPos,
                    arrowTop: input.arrowTop,
                    baseStateId: input.baseStateId,
                    deBuffEndTime: input.deBuffEndTime,
                };
                console.log("playerAttack playerId", input.playerId);
                this._state.arrows.push(newArrow);
                this.onNewArrow.forEach(v => v(newArrow));
            }
        }
        else if (input.type === 'PlayerJoin') {
            this.state.players.push({
                id: input.playerId,
                nickName: input.nickName,
                avatar: input.avatar,
                gold: input.gold,
                team: input.team,
                roomId: input.roomId,
                roomName: input.roomName,
                isReady: false,
                hp: 100,
                isRobot: false,
            })

            this._state.gameState = 1;
        } else if (input.type == 'RobotJoin') {
            this.state.players.push({
                id: input.robotId,
                nickName: input.nickName,
                avatar: input.avatar,
                gold: input.gold,
                team: input.team,
                roomId: input.roomId,
                roomName: input.roomName,
                isReady: true,
                hp: 100,
                isRobot: true
            })
        }
        else if (input.type === 'PlayerLeave') {

            if (this._state.gameState == 2) {
                //逃跑
                this.doResult(1, input.playerId);
            }
            this.state.players.remove(v => v.id === input.playerId);
            this.state.cirCleEles.remove(v => v.playerId === input.playerId);
            this.state.leftBaseEles.remove(v => v.playerId === input.playerId);
            this.state.rightBaseEles.remove(v => v.playerId === input.playerId);
            if (this.state.players.length <= 0) {
                this._state.players = [];
                this._state.resBaseEles = [];
                this._state.cirCleEles = [];
                this._state.leftBaseEles = [];
                this._state.rightBaseEles = [];
                this._state.gameState = 1;
            }

        }
        else if (input.type === 'TimePast') {
            this._state.now += input.dt;
            if (this._state.gameState == 3) return;

            /** 
           * 当时间小于
           */
            let now = Date.now();
            // 落地的 Arrow
            for (let i = this._state.arrows.length - 1; i > -1; --i) {
                let arrow = this._state.arrows[i];
                if (arrow.targetTime <= now) {
                    // 伤害判定
                    let player = this._state.players.find(v => v.id == arrow.fromPlayerId);
                    if (player) {
                        let childs = [];
                        if (player.team == 1) {
                            childs = this._state.leftBaseEles;
                        } else {
                            childs = this._state.rightBaseEles;
                        }
                        for (let i = childs.length - 1; i > -1; --i) {
                            let eBaseState = childs[i];
                            if (eBaseState) {
                                if (this.isCollide(arrow.targetPos, eBaseState.pos, 100) && (eBaseState.hp > 0)) {
                                    eBaseState.hp -= 1;
                                    eBaseState.deBuffEndTime = now + arrow.deBuffEndTime;
                                    if (eBaseState.hp <= 0) {
                                        let circleState = this._state.cirCleEles.find(v => v.id === eBaseState.cirCleStateId);
                                        if (circleState) {
                                            circleState.hp -= 1;
                                        }
                                        childs.splice(i, 1);

                                        if (eBaseState.type == soliderType.castle && this._state.gameState == 2) {
                                            this.doResult(2);
                                        }
                                    }

                                    if (eBaseState.type == soliderType.castle) {
                                        let playerState = this._state.players.find(v => v.id == eBaseState.playerId);
                                        if (playerState) {
                                            playerState.hp = eBaseState.hp;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    this._state.arrows.splice(i, 1);
                }
            }

            for (let i = this._state.rightBaseEles.length - 1; i > -1; --i) {
                let baseState = this._state.rightBaseEles[i];
                if (!baseState || !baseState.isCanMove) continue;
                let _moveAngle = 0;
                var nextNode = baseState.targetPosArr[baseState.nodeIndex];

                if (baseState.poolName == "spearman" || baseState.poolName == "fighter" || baseState.poolName == "shield" || baseState.poolName == "militia") {

                    nextNode = this.setPathCom(baseState, baseState.nodeIndex);
                    // console.log(nextNode);
                }

                if (!nextNode) {

                    continue;
                }
                var dx: number = nextNode.x - baseState.pos.x;
                var dy: number = nextNode.y - baseState.pos.y;

                var speed: number = baseState.moveSpeed * 0.1;
                if (dx * dx + dy * dy > speed * speed) {
                    if (_moveAngle == 0) {
                        _moveAngle = Math.atan2(dy, dx);
                    }

                    // this.scaleY = 1.5;
                    var xspeed: number = Math.cos(_moveAngle) * speed;
                    var yspeed: number = Math.sin(_moveAngle) * speed;

                    if (now > baseState.deBuffEndTime) {
                        baseState.pos.x += xspeed;
                        baseState.pos.y += yspeed;
                    } else {
                        //眩晕中，不移动
                    }

                } else {

                    if (baseState.nodeIndex == baseState.targetPosArr.length - 1) {
                        baseState.nodeIndex = 0;
                        this.setNextPos(baseState);
                    } else {
                        baseState.nodeIndex++;
                    }
                }


                this.isCollision(baseState, this._state.leftBaseEles, this._state.rightBaseEles, i);
            }

            for (let i = this._state.leftBaseEles.length - 1; i > -1; --i) {
                let baseState = this._state.leftBaseEles[i];
                if (!baseState || !baseState.isCanMove) continue;
                let _moveAngle = 0;
                var nextNode = baseState.targetPosArr[baseState.nodeIndex];

                if (baseState.poolName == "spearman" || baseState.poolName == "fighter" || baseState.poolName == "shield" || baseState.poolName == "militia") {

                    nextNode = this.setPathCom(baseState, baseState.nodeIndex);

                }

                if (!nextNode) {
                    continue;
                }
                var dx: number = nextNode.x - baseState.pos.x;
                var dy: number = nextNode.y - baseState.pos.y;

                var speed: number = baseState.moveSpeed * 0.05;
                if (dx * dx + dy * dy > speed * speed) {
                    if (_moveAngle == 0) {
                        _moveAngle = Math.atan2(dy, dx);
                    }

                    // this.scaleY = 1.5;
                    var xspeed: number = Math.cos(_moveAngle) * speed;
                    var yspeed: number = Math.sin(_moveAngle) * speed;

                    if (now > baseState.deBuffEndTime) {
                        baseState.pos.x += xspeed;
                        baseState.pos.y += yspeed;
                    } else {
                        //眩晕中，不移动
                    }

                } else {

                    if (baseState.nodeIndex == baseState.targetPosArr.length - 1) {
                        baseState.nodeIndex = 0;
                        this.setNextPos(baseState);
                    } else {

                        baseState.nodeIndex++;
                    }
                }

                this.isCollision(baseState, this._state.rightBaseEles, this._state.leftBaseEles, i);
            }


            if (this._state.gameOverTime <= now && this._state.gameState == 2) {
                this.doResult(2);
            }

            //定时增加金币
            if (this._state.goldTime <= now && this._state.gameState == 2) {
                this._state.players.forEach(ele => {
                    if (ele) {
                        this.applyInput({
                            type: "AddGold",
                            playerId: ele.id
                        })
                    }
                })
                this._state.goldTime = now + 3000;
            }

            /**
             * 清除圈
             */
            for (let i = 0; i < this._state.cirCleEles.length; i++) {
                let cirCleEle = this._state.cirCleEles[i];
                if (cirCleEle) {
                    if (cirCleEle.hp <= 0) {
                        this._state.cirCleEles.splice(i, 1);
                    }
                }
            }
        } else if (input.type == 'LocalTimePast') {
            this._state.now += input.dt;
        }
        else if (input.type == "BaseCreate") {
            //创建 圈和元素

            let playerState = this._state.players.find(v => v.id == input.playerId);

            if (!playerState) return;

            if (playerState?.gold < Number(input.needGold)) {
                return;
            }

            playerState.gold -= Number(input.needGold);

            let cirCleEle: CirCleState = {
                id: this._state.nextCirCleId++,
                playerId: input.playerId,
                pos: input.pos,
                cirCleType: input.cirCleType,
                hp: input.num,
                pos1: input.pos1,
                pos2: input.pos2,
                pos3: input.pos3,
                pos4: input.pos4,
                isMove: false,
            }

            if (cirCleEle.cirCleType) {
                this._state.cirCleEles.push(cirCleEle);
                this.onNewCirCle.forEach(v => v(cirCleEle));
            }

            for (let i = 0; i < input.num; i++) {
                let newBaseEle: BaseState = {
                    id: this._state.nextBaseEle++,
                    playerId: input.playerId,
                    pos: input.startPosArr[i],
                    poolName: input.poolName,
                    targetPosArr: input.targetPosArr,
                    nodeIndex: input.nodeIndex,
                    moveSpeed: input.moveSpeed,
                    speedX: input.speedX,
                    type: input.eleType,
                    campType: input.campType,
                    harvest: input.harvest,
                    harvestTime: input.harvestTime,
                    attack: input.attack,
                    hp: input.hp,
                    maxHp: input.maxHp,
                    isCanMove: input.isCanMove,
                    intval: input.intval,
                    cirCleStateId: cirCleEle.id,
                    baseId: input.baseId,
                    offX: input.offArr[i].x,
                    offY: input.offArr[i].y,
                    deBuffEndTime: 0
                };

                this.setNextPos(newBaseEle);

                if (input.team == 1) {
                    //右边
                    this._state.rightBaseEles.push(newBaseEle);
                } else if (input.team == 2) {
                    //左边
                    this._state.leftBaseEles.push(newBaseEle);
                }
            }
        } else if (input.type == "CircleMove") {
            //圈移动
            let cirCleEle = this._state.cirCleEles.find(v => v.id === input.circleId);
            if (!cirCleEle) {
                return;
            }
            cirCleEle.pos = input.pos;
            cirCleEle.pos1 = input.onePos;
            cirCleEle.pos2 = input.twoPos;
            cirCleEle.pos3 = input.threePos;
            cirCleEle.pos4 = input.fourPos;
        } else if (input.type == "smallCircleMove") {
            //小圈移动
            let cirCleEle = this._state.cirCleEles.find(v => v.id === input.circleId);
            if (!cirCleEle) {
                return;
            }
            // console.log(input);
            cirCleEle.pos1 = input.onePos;
            cirCleEle.pos2 = input.twoPos;
            cirCleEle.pos3 = input.threePos;
            cirCleEle.pos4 = input.fourPos;
            cirCleEle.isMove = input.isMove;
        } else if (input.type == "CreateRes") {
            //创建资源
            this._state.resBaseEles = [];
            this.createRes();
        } else if (input.type == "ResHurtBlood") {
            let resState;
            let j;
            for (let i = 0; i < this._state.resBaseEles.length; i++) {
                if (this._state.resBaseEles[i].id == input.resId) {
                    resState = this._state.resBaseEles[i];
                    j = i;
                    break;
                }
            }
            let playerState = this._state.players.find((v) => v.id == input.playerId);

            if (resState && j != undefined) {
                resState.hp = input.hp;
                if (resState.hp <= 0) {
                    this._state.resBaseEles.splice(j, 1);
                }
            }

            if (playerState) {
                playerState.gold = input.gold;
            }
        } else if (input.type == "PlayerReady") {
            let playerState = this._state.players.find(v => v.id == input.playerId);
            if (playerState) {
                playerState.isReady = true;
            }

            this._state.resBaseEles = [];
            this._state.cirCleEles = [];
            this._state.leftBaseEles = [];
            this._state.rightBaseEles = [];
            this._state.gameState = 1;

            if (this._state.players.length == 2) {
                let bool = true;
                this._state.players.forEach(ele => {
                    if (!ele.isReady) {
                        bool = false;
                    }
                })

                if (bool) {
                    this._state.gameState = 2;
                    let now = Date.now();
                    this._state.gameOverTime = (now + 120000);
                    this.applyInput({
                        type: "CreateRes",
                        playerId: 1
                    })

                    this._state.players.forEach(ele => {
                        this.createCastle(ele);
                        ele.gold = 120;
                    })

                    this._state.resultData = {};
                }
            }
        } else if (input.type == "DoGameResult") {

        } else if (input.type == "AddGold") {
            let playerState = this._state.players.find(v => v.id == input.playerId);
            if (playerState) {
                playerState.gold += 5;
            }
        }
    }

    /**
     * 结算
     */
    private async doResult(type: any, id: any = null) {
        if (this._state.gameState == 3) return;
        this._state.gameState = 3;
        this._state.gameOverTime = 0;

        this._state.players.forEach(ele => {
            if (ele) {
                ele.isReady = false;
            }
        })
        // console.log("type" )
        if (type == 1) {
            let player1 = this._state.players.find(v => v.id == id);
            let player2 = this._state.players.find(v => v.id != id);

            this._state.resultData = {
                txt1: `${player2?.nickName}胜利 +2积分`,
                txt2: `${player1?.nickName}逃跑 -4积分`
            }
        } else {
            let player1 = this._state.players[0];
            let player2 = this._state.players[1];

            if (player1.hp == player2.hp) {
                this._state.resultData = {
                    txt1: `平局`,
                    txt2: ``
                }
            } else {
                if (player1.hp > player2.hp) {

                    this._state.resultData = {
                        txt1: `${player1?.nickName}胜利 +4积分`,
                        txt2: `${player2?.nickName}失败 -4积分`
                    }
                } else {

                    this._state.resultData = {
                        txt1: `${player2?.nickName}胜利 +4积分`,
                        txt2: `${player1?.nickName}失败 -4积分`
                    }
                }
            }
        }
    }

    /**
     * 
     * @param node 
     * @param targetPos 
     * @returns 
     */
    private isCollide(node: { x: number, y: number }, targetPos: { x: number, y: number }, radiu: number = 60) {
        return Math.sqrt(Math.pow(node.x - targetPos.x, 2) + Math.pow(node.y - targetPos.y, 2)) < radiu;
    }

    /**
     * 碰撞检测
     */
    private isCollision(baseState: BaseState, childs: BaseState[], ownChilds: BaseState[], j: number) {

        if (baseState.type == soliderType.miner || baseState.type == soliderType.dogs) {
            for (let i = this._state.resBaseEles.length - 1; i > -1; --i) {
                let resState = this._state.resBaseEles[i];
                if (resState) {
                    if (this.isCollide(baseState.pos, resState.pos)) {
                        resState.harvestTime -= baseState.harvest;
                        if (resState.harvestTime <= 0) {
                            resState.harvestTime = 30;
                            // resState.hp--;
                            let playerState = this._state.players.find(v => v.id == baseState.playerId);
                            if (playerState) {
                                this.applyInput({
                                    type: "ResHurtBlood",
                                    resId: resState.id,
                                    hp: (resState.hp - 1),
                                    playerId: baseState.playerId,
                                    gold: (playerState.gold + 1)
                                })
                            }
                            // if (resState.hp <= 0) {
                            //     this._state.resBaseEles.splice(i, 1);
                            // }

                        }
                    }
                }
            }
        } else {

            for (let i = childs.length - 1; i > -1; --i) {
                let eBaseState = childs[i];
                if (eBaseState) {
                    if (this.isCollide(baseState.pos, eBaseState.pos) && (eBaseState.hp > 0) && (baseState.hp > 0)) {
                        eBaseState.hp -= baseState.attack;
                        baseState.hp -= eBaseState.attack;
                        if (eBaseState.hp <= 0) {
                            let circleState = this._state.cirCleEles.find(v => v.id === eBaseState.cirCleStateId);
                            if (circleState) {
                                circleState.hp -= 1;
                            }
                            childs.splice(i, 1);

                            if (eBaseState.type == soliderType.castle && this._state.gameState == 2) {
                                this.doResult(2);
                            }
                        }
                        if (baseState.hp <= 0) {
                            let circleState = this._state.cirCleEles.find(v => v.id === baseState.cirCleStateId);
                            if (circleState) {
                                circleState.hp -= 1;
                            }
                            ownChilds.splice(j, 1);
                            if (baseState.type == soliderType.castle && this._state.gameState == 2) {
                                this.doResult(2);
                            }
                        }

                        if (eBaseState.type == soliderType.castle) {
                            let playerState = this._state.players.find(v => v.id == eBaseState.playerId);
                            if (playerState) {
                                playerState.hp = eBaseState.hp;
                            }
                        }

                        if (baseState.type == soliderType.castle) {
                            let playerState = this._state.players.find(v => v.id == baseState.playerId);
                            if (playerState) {
                                playerState.hp = baseState.hp;
                            }
                        }

                    }
                }
            }
        }
    }

    /**
     * 创建城堡
     */
    createCastle(playerState: PlayerState) {
        let pos0 = playerState.team == 2 ? { x: -380, y: 0 } : { x: 380, y: 0 };
        let pos1 = { x: 0, y: 0 };
        let pos2 = { x: 0, y: 0 };
        let pos3 = { x: 0, y: 0 };
        let pos4 = { x: 0, y: 0 };

        this.applyInput({
            type: "BaseCreate",
            playerId: playerState.id,
            pos: { x: 0, y: 0 },
            num: 1,
            cirCleType: "",
            pos1: pos1,
            pos2: pos2,
            pos3: pos3,
            pos4: pos4,
            startPosArr: [pos0],
            poolName: "castle",
            targetPosArr: [],
            nodeIndex: 0,
            moveSpeed: 0,
            speedX: 1,
            eleType: soliderType.castle,
            campType: playerState.team == 1 ? 1 : 2,
            harvest: 0,
            harvestTime: 0,
            attack: 1,
            hp: 100,
            maxHp: 100,
            isCanMove: true,
            intval: 0,
            team: playerState.team,
            baseId: 0,
            offArr: [{ x: 0, y: 0 }],
            needGold: 0,
        })
    }

    /**
     * 创建中立资源
     */
    createRes() {
        console.log("createRessssssss")
        let arr = [
            { x: -80, y: 180, maxHp: 50, hp: 50, iconUrl: "ele/mineral_1", poolName: "mineral" },
            { x: 0, y: 180, maxHp: 50, hp: 50, iconUrl: "ele/mineral_2", poolName: "mineral" },
            { x: 80, y: 180, maxHp: 50, hp: 50, iconUrl: "ele/mineral_3", poolName: "mineral" },
            { x: -40, y: 100, maxHp: 10, hp: 10, iconUrl: "ele/tree_1", poolName: "tree" },
            { x: 40, y: 100, maxHp: 10, hp: 10, iconUrl: "ele/tree_2", poolName: "tree" },
            { x: -40, y: 20, maxHp: 10, hp: 10, iconUrl: "ele/tree_3", poolName: "tree" },
            { x: 40, y: 20, maxHp: 10, hp: 10, iconUrl: "ele/tree_1", poolName: "tree" },
            { x: -40, y: -60, maxHp: 10, hp: 10, iconUrl: "ele/tree_2", poolName: "tree" },
            { x: 40, y: -60, maxHp: 10, hp: 10, iconUrl: "ele/tree_3", poolName: "tree" },
            { x: -40, y: -140, maxHp: 50, hp: 50, iconUrl: "ele/mineral_1", poolName: "mineral" },
            { x: 40, y: -140, maxHp: 50, hp: 50, iconUrl: "ele/mineral_2", poolName: "mineral" },
            { x: -80, y: -220, maxHp: 50, hp: 50, iconUrl: "ele/mineral_3", poolName: "mineral" },
            { x: 0, y: -220, maxHp: 50, hp: 50, iconUrl: "ele/mineral_1", poolName: "mineral" },
            { x: 80, y: -220, maxHp: 50, hp: 50, iconUrl: "ele/mineral_2", poolName: "mineral" },
        ];

        for (let i: number = 0; i < arr.length; i++) {
            // if (this._state.resBaseEles.find(v => v.posId == i)) {
            //     continue;
            // }

            let newResState: ResState = {
                id: this._state.nextResId++,
                pos: arr[i],
                posId: i,
                maxHp: arr[i].maxHp,
                hp: arr[i].hp,
                harvestTime: 30,
                poolName: arr[i].poolName,
                iconUrl: arr[i].iconUrl
            }

            this._state.resBaseEles.push(newResState);
        }
    }

    /**
     * 设置小圈路径
     */
    private setPathCom(baseState: BaseState, num: number) {

        let pos: { x: number, y: number } = { x: 0, y: 0 };
        let circleState = this._state.cirCleEles.find(v => v.id === baseState.cirCleStateId);
        if (circleState)
            switch (num) {
                case 0:
                    pos = circleState.pos1;
                    break;
                case 1:
                    pos = circleState.pos2;;
                    break;
                case 2:
                    pos = circleState.pos3;;
                    break;
                case 3:
                    pos = circleState.pos4;;
                    break;
            }

        if (pos) {
            pos = { x: pos.x + baseState.offX, y: pos.y + baseState.offY };
        }
        return pos;
    }

    private setNextPos(baseState: BaseState) {

        baseState.nodeIndex = 0;
        // console.log(baseState.type, baseState.type == soliderType.dogs)
        let circleState = this._state.cirCleEles.find(v => v.id === baseState.cirCleStateId);

        if (baseState.type == soliderType.dogs) {
            if (circleState) {
                let x = Math.random() * 200 - 100;
                let y = Math.random() * 120 - 70;
                baseState.targetPosArr = [{ x: x + circleState.pos.x, y: y + circleState.pos.y }];
            }
        } else if (baseState.type == soliderType.miner) {
            if (circleState) {
                let x = Math.random() * 150 - 75;
                let y = Math.random() * 90 - 52;
                baseState.targetPosArr = [{ x: x + circleState.pos.x, y: y + circleState.pos.y }];
            }
        } else if (baseState.type == soliderType.master || baseState.type == soliderType.warlock || baseState.type == soliderType.logistics) {
            if (circleState) {
                let x = Math.random() * 100 - 50;
                let y = Math.random() * 60 - 35;
                baseState.targetPosArr = [{ x: x + circleState.pos.x, y: y + circleState.pos.y }];
            }
        } else if (baseState.type == soliderType.guard) {
            if (circleState) {
                let arr = [{ x: -25, y: 25 }, { x: -25, y: -25 }, { x: 25, y: -25 }, { x: 25, y: 25 }];
                for (let i = 0; i < arr.length; i++) {
                    arr[i].x += baseState.offX + circleState.pos.x;
                    arr[i].y += baseState.offY + circleState.pos.y;
                }
                baseState.targetPosArr = arr;
            }
        } else if (baseState.type == soliderType.bowman) {
            if (circleState) {
                let arr = [{ x: -25, y: 20 }, { x: -25, y: -20 }, { x: 25, y: -20 }, { x: 25, y: 20 }];
                for (let i = 0; i < arr.length; i++) {
                    arr[i].x += baseState.offX + circleState.pos.x;
                    arr[i].y += baseState.offY + circleState.pos.y;
                }
                baseState.targetPosArr = arr;
            }
        } else if (baseState.type == soliderType.swordsman) {
            if (circleState) {
                let arr = [{ x: -30, y: 25 }, { x: -30, y: -25 }, { x: 30, y: -25 }, { x: 30, y: 25 }];
                for (let i = 0; i < arr.length; i++) {
                    arr[i].x += baseState.offX + circleState.pos.x;
                    arr[i].y += baseState.offY + circleState.pos.y;
                }
                baseState.targetPosArr = arr;
            }
        } else if (baseState.type == soliderType.cavalry) {
            if (circleState) {
                let arr = [{ x: -85, y: 60 }, { x: -85, y: -60 }, { x: 85, y: -60 }, { x: 85, y: 60 }];
                for (let i = 0; i < arr.length; i++) {
                    arr[i].x += baseState.offX + circleState.pos.x;
                    arr[i].y += baseState.offY + circleState.pos.y;
                }
                baseState.targetPosArr = arr;
            }
        }
    }

    /*
     * 事件
     * 某些转瞬即逝的事件，可能不会直观的体现在前后两帧状态的变化中，但表面层又需要知晓。
     * 例如一颗狙击枪的子弹，在少于一帧的时间内创建和销毁，前后两帧的状态中都不包含这颗子弹；但表现层却需要绘制出子弹的弹道。
     * 此时，可以通过事件的方式通知表现层。
     */
    // 发射箭矢
    onNewArrow: ((arrow: ArrowState) => void)[] = [];

    //创建圈
    onNewCirCle: ((circle: CirCleState) => void)[] = [];

    //创建元素
    onNewBaseEle: ((baseEle: BaseState) => void)[] = [];
}

export interface PlayerMove {
    type: 'PlayerMove',
    playerId: number,
    speed: { x: number, y: number },
    // 移动的时间 (秒)
    dt: number,
}
export interface PlayerAttack {
    type: 'PlayerAttack',
    playerId: number,
    // 落点坐标
    targetPos: { x: number, y: number },
    // 落点时间（游戏时间）
    targetTime: number,
    //箭的类型
    arrowType: string,
    startPos: { x: number, y: number },
    arrowTop: number,
    baseStateId: number,
    deBuffEndTime: number,
}
export interface PlayerJoin {
    type: 'PlayerJoin',
    playerId: number,
    nickName: string,
    avatar: string,
    gold: number,
    team: number,
    roomId: string,
    roomName: string,
}

export interface RobotJoin {
    type: 'RobotJoin',
    playerId: number,
    robotId: number,
    nickName: string,
    avatar: string,
    gold: number,
    team: number,
    roomId: string,
    roomName: string,
}

export interface PlayerLeave {
    type: 'PlayerLeave',
    playerId: number
}
// 时间流逝
export interface TimePast {
    type: 'TimePast',
    dt: number
}

// 本地时间流逝
export interface LocalTimePast {
    type: 'LocalTimePast',
    dt: number
}

//创建元素
export interface BaseCreate {
    type: 'BaseCreate',
    playerId: number,
    pos: { x: number, y: number },
    cirCleType: string,
    num: number,
    pos1: { x: number, y: number },
    pos2: { x: number, y: number },
    pos3: { x: number, y: number },
    pos4: { x: number, y: number },
    startPosArr: { x: number, y: number }[],
    poolName: string,
    targetPosArr: { x: number, y: number }[],
    nodeIndex: number,
    moveSpeed: number,
    speedX: number,
    eleType: number,
    campType: number,
    harvest: number,
    harvestTime: number,
    attack: number,
    hp: number,
    maxHp: number,
    isCanMove: boolean,
    intval: number,
    team: number,
    baseId: number,
    offArr: { x: number, y: number }[],
    needGold: number,
}

export interface CircleMove {
    type: "CircleMove",
    playerId: number,
    pos: { x: number, y: number },
    circleId: number,
    onePos: { x: number, y: number },
    twoPos: { x: number, y: number },
    threePos: { x: number, y: number },
    fourPos: { x: number, y: number },
}

export interface smallCircleMove {
    type: "smallCircleMove",
    playerId: number,
    circleId: number,
    isMove: boolean,
    onePos: { x: number, y: number },
    twoPos: { x: number, y: number },
    threePos: { x: number, y: number },
    fourPos: { x: number, y: number },
}

export interface CreateRes {
    type: 'CreateRes',
    playerId: number
}

export interface ResHurtBlood {
    type: "ResHurtBlood",
    resId: number,
    hp: number,
    playerId: number,
    gold: number,
}

export interface PlayerReady {
    type: "PlayerReady",
    playerId: number,
}

export interface DoGameResult {
    type: "DoGameResult",
    playerId: number,
}

/**
 * 增加金币
 */
export interface AddGold {
    type: "AddGold",
    playerId: number,
}

// 输入定义
export type GameSystemInput = PlayerMove
    | PlayerAttack
    | PlayerJoin
    | PlayerLeave
    | TimePast
    | BaseCreate
    | CircleMove
    | smallCircleMove
    | LocalTimePast
    | CreateRes
    | ResHurtBlood
    | PlayerReady
    | DoGameResult
    | AddGold
    | RobotJoin
    ;